package com.bradz.mymovies;

import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.SubMenu;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.View.OnTouchListener;
import android.widget.FrameLayout;
import android.widget.MediaController;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.VideoView;

public class ActivityMediaPlayer extends Activity{
	
	//Remember to add the swipe controls to the media player before this goes out
	
	private VideoView myVideoView;
	//private boolean sound_paused = false;
	private boolean show_toast = false;
	//private boolean movie_lock = false;
	private Context self;
	private String path;
	private ArrayList<File> shows;
	private static String TAG;
	private int error_counter;
	private ApplicationGlobalVars globals;
	private String[] errors = {"Bad Picture", "Bad Sound", "No Subtitles", "Other"};
	private String[] services = {"Android"};
	private BroadcastReceiver mReceiver;
	private Random rand = new Random(System.nanoTime());
    private ClassNetworkHelper helper;
	
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
	    setContentView(R.layout.activity_media_player);
	    
	    globals = ((ApplicationGlobalVars) this.getApplication());
	    helper = new ClassNetworkHelper(this,globals);

	    TAG = "myMovies";
	    register_receiver();
	    
	    myVideoView = (VideoView)findViewById(R.id.media_player);
	    
	    
	    final FrameLayout loading_frame = (FrameLayout) findViewById(R.id.loading_frame);
	    loading_frame.setVisibility(View.INVISIBLE);
	    
	    if(globals.played_something()){
		    loading_frame.setVisibility(View.VISIBLE);
		    globals.did_play();
		    Runnable mRunnable;
		    Handler mHandler=new Handler();

		    mRunnable=new Runnable() {
	                @Override
	                public void run() {
	                    // TODO Auto-generated method stub
	                	loading_frame.setVisibility(View.INVISIBLE);
	                }
	            };
		    
	        mHandler.postDelayed(mRunnable,10*1000);
	    }
    	globals.set_buffer("");
	    Intent intent = getIntent();
	    path = intent.getStringExtra("PATH_ID");
	    self = this;
	    
        show_music_data();
        
        //The only reason this variable has to be here is because some dumbass thought
        //that it would be a good idea to keep plugging in usb drives with poorly formatted
        //media, crashing the system when onErrorRepeats
        error_counter = 0;
        
        FrameLayout lowestLayout = (FrameLayout) this.findViewById(R.id.content_frame);
        lowestLayout.setOnTouchListener(new OnSwipeTouchListener());
        
        shows = new ArrayList<File>(Arrays.asList((new File(path)).getParentFile().listFiles()));
	    load_movie(path,0,setVolume(globals.get_mute()?0:100));
	}
	
	@Override
	public void onResume(){
		super.onResume();
		try{
			show_toast = true;
			register_receiver();
		}catch(Exception e){
			Log.e(TAG, e.toString());
		}
	}
	
	@Override
	public void onPause(){
		super.onPause();
		try{
			show_toast = false;
			unregisterReceiver(mReceiver);
		}catch(Exception e){
			Log.e(TAG, e.toString());
		}
	}
	
	public void register_receiver(){
		mReceiver = new BroadcastReceiver() { 
			
			@Override
	        public void onReceive(Context context, Intent intent)
	        {
		        String action = intent.getAction();
		        String cmd = intent.getStringExtra("command");
		        Log.d(TAG, action + " / " + cmd);
		        String artist = intent.getStringExtra("artist");
		        //String album = intent.getStringExtra("album");
		        String track = intent.getStringExtra("track");
		        if(show_toast){
		        	Toast.makeText(self, artist + " - " + track, Toast.LENGTH_LONG).show();
		        }
	        }
		};
	}
	
	public String get_path_file(){
		return (new File(path)).getName();
	}
	
	/*public void pick_random_movie(){
		Random rand = new Random(System.nanoTime());
		shows = new ArrayList<File>(Arrays.asList((new File(path)).getParentFile().listFiles()));
		Intent intent = new Intent(getBaseContext(), mediaPlayer.class);
        intent.putExtra("PATH_ID", shows.get(rand.nextInt(shows.size())).getAbsolutePath());
        intent.putExtra("MUTE", sound_paused);
        intent.putExtra("LOCK", movie_lock);
        startActivity(intent);
	}*/
	
	public void pick_random_movie(boolean random_offset){
		//Random rand = new Random(System.nanoTime());
		//shows = new ArrayList<File>(Arrays.asList((new File(path)).getParentFile().listFiles()));
		if(random_offset){
			load_movie(shows.get(rand.nextInt(shows.size())).getAbsolutePath(),-1,setVolume(globals.get_mute()?0:100));
		}else{
			load_movie(shows.get(rand.nextInt(shows.size())).getAbsolutePath(),0,setVolume(globals.get_mute()?0:100));
		}
	}
	
	public void pick_random_movie(int index){
		//shows = new ArrayList<File>(Arrays.asList((new File(path)).getParentFile().listFiles()));
		load_movie(shows.get(index).getAbsolutePath(),0,setVolume(globals.get_mute()?0:100));
	}
	
	public void load_movie(final String path, final int position, final float volume){
		this.path = path;
	    myVideoView.setVideoPath(path);
	    myVideoView.requestFocus();
	    myVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
	        @Override
	        public void onCompletion(MediaPlayer mp) {
	        	//When the movie is complete, destroy the media player and return to the select screen
	        	if(globals.get_lock()){
	        		pick_random_movie(false);
	        	}else{
	        		finish();
	        	}
	        }
	    });
	    myVideoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
	        public boolean onError(MediaPlayer mp, int what, int extra) {
	        	AlertDialog.Builder dialog = new AlertDialog.Builder(ActivityMediaPlayer.this);
                dialog.setTitle("Error");
                dialog.setMessage("Media File: " + path + "\nIs not supported by Android. Please remove from folder in the future.");
	        	
                List<NameValuePair> pairs = new ArrayList<NameValuePair>();
  			  	pairs.add(new BasicNameValuePair("error", "System Generated"));
        		pairs.add(new BasicNameValuePair("asset", path));
        		helper.send_message(pairs,"set_error/");
                
                final AlertDialog dlg = dialog.create();
                
                dlg.show();
                
                final Timer timer=new Timer();
                timer.schedule(new TimerTask() {
                    @Override  public void run() {  
                        dlg.dismiss();
                        timer.cancel();
                    }
                }, 7000);
	        	
                error_counter++;
                if(error_counter == shows.size()){
                	finish();
                }else{
                    load_movie(shows.get(rand.nextInt(shows.size())).getAbsolutePath(),position,setVolume(globals.get_mute()?0:100));
                }
                
	        	return true;
	        }

	    });
	    myVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener()  {
            @Override
            public void onPrepared(MediaPlayer mp) {  
            	error_counter = 0;
            	if(globals.get_mute()){
            		show_toast = true;
            		//Toast.makeText(self, "Audio:Music", Toast.LENGTH_LONG).show();
    	    		Intent i = new Intent("com.android.music.musicservicecommand");
    	            i.putExtra("command", "play");
    	            self.sendBroadcast(i);
            	}
            	
            	if(position == -1){
            		//rand.nextInt(shows.size())
            		//myVideoView.getDuration()
            		//Make sure that the move lands between 1/6 and 5/6 of the offset
            		int video_duration = myVideoView.getDuration();
            		int min_time = video_duration/6;
            		int duration_window = 4*min_time;
            		mp.seekTo(min_time + rand.nextInt(duration_window));
            	}else{
                	mp.seekTo(position);
            	}
            	mp.setVolume(volume, volume);
            	mp.start();
            }
	    });
	}
	
	// We want to create a context Menu when the user long click on an item
  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
	  Log.i(TAG,(new File(path)).getParentFile().getAbsolutePath());
	  
      //shows = new ArrayList<File>(Arrays.asList((new File(path)).getParentFile().listFiles()));
      Collections.reverse(shows);
      SubMenu showMenu = menu.addSubMenu("Select Media");
      SubMenu errorMenu = menu.addSubMenu("Submit Error");
      SubMenu resync = menu.addSubMenu("ReSync Service");
      for(int i = 0; i < shows.size();i++){
    	  showMenu.add(2,i, i, shows.get(i).getName());
      }
      for(int i = 0; i < errors.length;i++){
    	  errorMenu.add(3,i, i, errors[i]);
      }
      for(int i = 0; i < services.length;i++){
    	  resync.add(4,i, i, services[i]);
      }
      return super.onPrepareOptionsMenu(menu);
  }

  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
      int itemId = item.getItemId();
      int groupId = item.getGroupId();
      Log.i(TAG,"Clicked: " + String.valueOf(itemId));
      if (!item.hasSubMenu()){
    	  Log.i(TAG,"Doesn't have submenu. Selecting...");
    	  if(groupId == 2 && itemId >=0){
    		  pick_random_movie(itemId);
    	  }
    	  else if(groupId == 3 && itemId >=0 && itemId < errors.length){
    		  List<NameValuePair> pairs = new ArrayList<NameValuePair>();
			  pairs.add(new BasicNameValuePair("error", errors[itemId]));
      		  pairs.add(new BasicNameValuePair("asset", path));
      		  helper.send_message(pairs,"set_error/");
    	  }else if(groupId == 4 && itemId >=0){
    		  helper.log_into_network();
    	  }
      }
    return false;
  }
		  
	@Override
    /**
     * Overrides the callback method for a UI control handling a Movie
     **/
    public boolean onKeyDown(int keyCode, KeyEvent event) {

      /*
       * Chooses the action to take, based on the incoming keycode
       */
      switch (keyCode) {
            
        case KeyEvent.KEYCODE_DPAD_UP:
        	//The movie sound is paused and needs to be turned back on again
        	if(globals.get_mute()){
        		show_toast = false;
        		Toast.makeText(self, get_path_file(), Toast.LENGTH_LONG).show();
	    		Intent i = new Intent("com.android.music.musicservicecommand");
	            i.putExtra("command", "pause");
	            self.sendBroadcast(i);
	            globals.set_mute(false);
        		unmute();
        	}else{
        		show_toast = true;
        		//Toast.makeText(self, "Audio:Music", Toast.LENGTH_LONG).show();
	    		Intent i = new Intent("com.android.music.musicservicecommand");
	            i.putExtra("command", "play");
	            self.sendBroadcast(i);
	            globals.set_mute(true);
        		mute();
            }
            
            return true;
        case KeyEvent.KEYCODE_DPAD_RIGHT:
        	if(globals.get_mute()){
        		show_toast = true;
        		Intent i = new Intent("com.android.music.musicservicecommand");
	            i.putExtra("command", "next");
	            self.sendBroadcast(i);
            }
            
            return true;
        case KeyEvent.KEYCODE_DPAD_LEFT:
        	if(globals.get_mute()){
        		show_toast = true;
	    		Intent i = new Intent("com.android.music.musicservicecommand");
	            i.putExtra("command", "previous");
	            self.sendBroadcast(i);
            }
            
            return true;
        
        case KeyEvent.KEYCODE_DPAD_DOWN:
        	if(globals.get_mute()){
        		Toast.makeText(self, "Audio:Music TogglePause", Toast.LENGTH_LONG).show();
        		show_toast = false;
	    		Intent i = new Intent("com.android.music.musicservicecommand");
	            i.putExtra("command", "togglepause");
	            self.sendBroadcast(i);
            }
        	return true;    
            
        case KeyEvent.KEYCODE_ENTER:
        	Toast.makeText(self, get_path_file(), Toast.LENGTH_LONG).show();
        	
        	//if(sound_paused){
        		//Toast.makeText(self, "Audio:Music", Toast.LENGTH_LONG).show();
        		//show_toast = true;
	    		//Intent i = new Intent("com.android.music.musicservicecommand");
	            //i.putExtra("command", "play");
	            //this.sendBroadcast(i);
            //}
            
            return true;
        
        case KeyEvent.KEYCODE_L:
        	globals.set_lock(!globals.get_lock());
        	Toast.makeText(self, "Movie Lock: " + String.valueOf(globals.get_lock()), Toast.LENGTH_LONG).show();
        	return true;
            
        case KeyEvent.KEYCODE_DPAD_CENTER:
        	pick_random_movie(true);
        	return true;
            
        case KeyEvent.KEYCODE_MEDIA_PAUSE:
        	show_toast = false;
        	if(myVideoView.isPlaying()){
        		myVideoView.pause();
        	}else{
        		myVideoView.start();
        	}
        	return true;
        
        case KeyEvent.KEYCODE_MEDIA_PLAY:
        	show_toast = false;
        	myVideoView.start();
            return true;
            
        case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
        	show_toast = false;
        	myVideoView.seekTo(myVideoView.getCurrentPosition()+20000);
            return true;
            
        case KeyEvent.KEYCODE_MEDIA_REWIND: 
        	show_toast = false;
        	myVideoView.seekTo(myVideoView.getCurrentPosition()-10000);
            return true;

        default:
          return super.onKeyDown(keyCode, event);
      }
    }
	
	public void show_music_data(){
		IntentFilter iF = new IntentFilter();
        iF.addAction("com.android.music.metachanged");
        iF.addAction("com.android.music.playstatechanged");
        iF.addAction("com.android.music.playbackcomplete");
        iF.addAction("com.android.music.queuechanged"); 
        registerReceiver(mReceiver, iF);
	}
	
	public void mute() {
        load_movie(path,myVideoView.getCurrentPosition(),setVolume(0));
    }

    public void unmute() {
        load_movie(path,myVideoView.getCurrentPosition(),setVolume(100));
    }

    private float setVolume(int amount) {
        final int max = 100;
        final double numerator = max - amount > 0 ? Math.log(max - amount) : 0;

        return (float) (1 - (numerator / Math.log(max)));
    }
    
  //This is the gesture control for the phone controls
  	public class OnSwipeTouchListener implements OnTouchListener {

  	    private final GestureDetector gestureDetector = new GestureDetector(new GestureListener());

  	    public boolean onTouch(final View view, final MotionEvent motionEvent) {
  	        return gestureDetector.onTouchEvent(motionEvent);
  	    }

  	    private final class GestureListener extends SimpleOnGestureListener {

  	    	private final ViewConfiguration vc = ViewConfiguration.get(self);
  			private final int SWIPE_THRESHOLD = vc.getScaledPagingTouchSlop();
  		    private final int SWIPE_VELOCITY_THRESHOLD = vc.getScaledMinimumFlingVelocity();

  	        @Override
  	        public boolean onDown(MotionEvent e) {
  	        	Log.i(TAG + " down", "swiper");
  	            return true;
  	        }

  	        @Override
            public boolean onDoubleTap(MotionEvent e) {
              Log.i(TAG + " double_tap", "onDoubleTap");
              onTwoTaps();
              return super.onDoubleTap(e);
            }
  	        
  	        @Override
  	        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
  	        	Log.i(TAG + " fling", "swiper");
  	            boolean result = false;
  	            try {
  	                float diffY = e2.getY() - e1.getY();
  	                float diffX = e2.getX() - e1.getX();
  	                if (Math.abs(diffX) > Math.abs(diffY)) {
  	                    if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
  	                        if (diffX > 0) {
  	                            onSwipeRight();
  	                        } else {
  	                            onSwipeLeft();
  	                        }
  	                    }
  	                } else {
  	                    if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
  	                        if (diffY > 0) {
  	                            onSwipeBottom();
  	                        } else {
  	                            onSwipeTop();
  	                        }
  	                    }
  	                }
  	            } catch (Exception exception) {
  	                exception.printStackTrace();
  	            }
  	            return result;
  	        }
  	    }

  	    public void onTwoTaps() {
  	    	//Two taps on a phone is the same as clicking the center button on googleTV
  	    	pick_random_movie(true);
	    }
  	    
  	    public void onSwipeRight() {
  	    	if(globals.get_mute()){
        		show_toast = true;
        		Intent i = new Intent("com.android.music.musicservicecommand");
	            i.putExtra("command", "next");
	            self.sendBroadcast(i);
            }else{
            	show_toast = false;
            	myVideoView.seekTo(myVideoView.getCurrentPosition()+20000);
            }
  	    }

  	    public void onSwipeLeft() {
  	    	if(globals.get_mute()){
        		show_toast = true;
	    		Intent i = new Intent("com.android.music.musicservicecommand");
	            i.putExtra("command", "previous");
	            self.sendBroadcast(i);
            }else{
            	show_toast = false;
            	myVideoView.seekTo(myVideoView.getCurrentPosition()-10000);
            }
  	    }

  	    public void onSwipeTop() {
  	    	if(globals.get_mute()){
        		show_toast = false;
        		Toast.makeText(self, get_path_file(), Toast.LENGTH_LONG).show();
	    		Intent i = new Intent("com.android.music.musicservicecommand");
	            i.putExtra("command", "pause");
	            self.sendBroadcast(i);
	            globals.set_mute(false);
        		unmute();
        	}else{
        		show_toast = true;
        		//Toast.makeText(self, "Audio:Music", Toast.LENGTH_LONG).show();
	    		Intent i = new Intent("com.android.music.musicservicecommand");
	            i.putExtra("command", "play");
	            self.sendBroadcast(i);
	            globals.set_mute(true);
        		mute();
            }
  	    }

  	    public void onSwipeBottom() {
  	    	show_toast = false;
  	    	//Check if the music is playing over the movie
  	    	if(globals.get_mute()){
  	    		//If the music is playing, toggle the music pause
  	    		Toast.makeText(self, "Audio:Music TogglePause", Toast.LENGTH_LONG).show();
        		show_toast = false;
	    		Intent i = new Intent("com.android.music.musicservicecommand");
	            i.putExtra("command", "togglepause");
	            self.sendBroadcast(i);
  	    	}else{
  	    		//If it isn't, toggle the movie pause
  	    		show_toast = false;
  	    		if(myVideoView.isPlaying()){
	        		myVideoView.pause();
	        	}else{
	        		myVideoView.start();
	        	}
  	    	}
  	    }
  	}

}